<template>
  <div class="canvas-wrapper">
    <div id="editor-canvas"></div>
    <editor-context-menu v-model:visible="showContextmenu" :x="positionX" :y="positionY" :menu-list="contextmenuList"
      @menuClick="onContextMenuClick" />
    <!-- <el-dialog v-model="dialogVisible" :title="dialogTitle" @sure="sure" @cancel="dialogVisible = false" append-to-body>
      绑定设备：{{ bindDataList }}
    </el-dialog> -->
  </div>
</template>

<script setup lang="ts">
import datainput from "@/views/operate/device-management/device-management/components/datainput.vue";
import { EditorActiveType } from "@/components/TopologyEditor/constant";
import {
  LockState,
  Meta2d,
  addLineAnchor,
  type Pen,
  type Point
} from "@meta2d/core";
import EditorContextMenu from "./EditorContextMenu.vue";
import { useTopologyEditorStore } from "@/store/modules/topology-editor";
import type { ContextMenuItem } from "types/editor";
// import { myTriangle, myTriangleAnchors } from '@/../public/path2D/mypath2d/myTriangle.js'
// import { canvasTriangle, canvasTriangleAnchors } from '@/../public/canvasDraw/myCanvasDraw/canvasTriangle.js'
import { flowPens } from "@meta2d/flow-diagram";
import { ElLoading } from "element-plus";
import {
  activityDiagram,
  activityDiagramByCtx
} from "@meta2d/activity-diagram";
import { sequencePens, sequencePensbyCtx } from "@meta2d/sequence-diagram";
import { classPens } from "@meta2d/class-diagram";
import { collapseChildPlugin } from "@meta2d/plugin-mind-collapse";
import { mindBoxPlugin } from "@meta2d/plugin-mind-core";
import {
  register as registerEcharts,
  registerHighcharts,
  registerLightningChart
} from "@meta2d/chart-diagram"; // 引入echarts注册函数，原函数名为register 为了与其他注册函数区分这里重命名为registerEcharts
import { formPens } from "@meta2d/form-diagram";
import { deviceControl, commandconfig } from "@/api/topo/index";
import {
  ElMessage,
  ElMessageBox,
  ElOption,
  ElSelect,
  ElSwitch
} from "element-plus";
import { addDialog, closeDialog } from "@/components/ReDialog";
import dataselect from "./dataselect.vue";
import { customPromiseDebounce } from "@/utils/functions";
import { configurationPageStore } from "@/store/modules/configurationPage";
import { isFunction } from "@pureadmin/utils";
const store = useTopologyEditorStore();

// eslint-disable-next-line @typescript-eslint/no-explicit-any
declare const window: any;

defineOptions({
  name: "EditorCanvas"
});

const props = defineProps({
  editable: {
    type: Boolean,
    default: true
  }
});
const loadingopen = ref(null);
const router = useRouter();
const query = reactive(router.currentRoute.value.query);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const bindDataInfo = ref([] as any[]);
const bindDataList = ref([] as any[]);
const showContextmenu = ref(false);
const positionX = ref(0);
const positionY = ref(0);
let contextmenuList = ref<Array<ContextMenuItem>>([]);
const timer = ref(null);
onMounted(() => {
  initMeta2d();
  initEventListener();
});
const sure = () => {
  dialogVisible.value = false;
};

const configurationPage = configurationPageStore();
// 遍历对象的所有属性与值
const selectAllProperty = (obj: any) => {
  for (const key in obj) {
    if (typeof obj[key] === "object" && obj[key] !== null) {
      selectAllProperty(obj[key]);
    } else if (
      key == "formatter" &&
      typeof obj[key] === "string" &&
      obj[key].indexOf("{") != 0
    ) {
      obj[key] = eval(obj[key]);
    }
  }
};
const setTimer = meta2d => {
  timer.value = setInterval(() => {
    const now = new Date();
    meta2d.setValue({
      dataId: "LocTime",
      value: `${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日`
    });
    meta2d.setValue({
      dataId: "LocWeek",
      value: `周${["日", "一", "二", "三", "四", "五", "六"][now.getDay()]}`
    });
    meta2d.setValue({
      dataId: "LocAllTime",
      value: `${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日 ${now.getHours()}时${now.getMinutes()}分${now.getSeconds()}秒`
    });
  }, 1000);
};
const clearTimer = () => {
  if (timer.value) {
    clearInterval(timer.value);
  }
};
function initMeta2d() {
  const options = {
    fontFamily: 'Arial, "Microsoft YaHei"',
    grid: query.type == "1",
    rule: query.type == "1"
  };
  let meta2d = new Meta2d("editor-canvas", options);
  window.meta2d.setBackgroundColor("#f4f4f4");
  meta2d.register(flowPens());

  // 注册注册活动图元
  meta2d.register(activityDiagram());
  // 原生canvas绘画的图库，支持逻辑复杂的需求
  meta2d.registerCanvasDraw(activityDiagramByCtx());

  // 注册时序图
  meta2d.register(sequencePens());
  meta2d.registerCanvasDraw(sequencePensbyCtx());
  meta2d.installPenPlugins({ name: "mindNode2" }, [
    {
      plugin: mindBoxPlugin
    },
    {
      plugin: collapseChildPlugin
    }
  ]);

  // 注册类图
  meta2d.register(classPens());
  // uninstallPlugin('toolBox')
  // 注册表单图元
  meta2d.registerCanvasDraw(formPens());
  // 直接调用Echarts的注册函数
  registerEcharts();

  // 直接调用HighCharts的注册函数
  registerHighcharts();
  // 直接调用LightningChart的注册函数
  registerLightningChart();
  //注册自定义path2d图元
  // meta2d.register({ myTriangle })
  // 注册自定义图元的m锚点信息
  // meta2d.registerAnchors({ myTriangle: myTriangleAnchors })

  // 注册自定义canvasDraw函数
  // meta2d.registerCanvasDraw({ canvasTriangle })
  //注册锚点
  // meta2d.registerAnchors({ canvasTriangle: canvasTriangleAnchors })
  // event.customEmit('opened')
  // event.customEmit('load')
  setTimer(meta2d);
  meta2d.beforeAddPens = pens =>
    new Promise<boolean>((resolve, reject) => {
      pens.forEach(item => {
        if (item?.echarts) {
          selectAllProperty(item?.echarts);
        }
        console.log(item);
        delete item.form;
        delete item.events;
        delete item.realTimeData;
        delete item.eventsData;
        delete item.controlCommand;
        if (item.name == "time") {
          item.form = [
            {
              key: "text",
              dataIds: {
                dataId: "LocAllTime"
              }
            }
          ];
        }
      });
      resolve(true);
    });
  meta2d.on("showBindData", e => {
    // dialogTitle.value = '图元详情'
    // dialogVisible.value = true
    // bindDataInfo.value = e.pen.form
    if (query.type == "1") {
      console.log("编辑模式不可触发控制命令");
    } else {
      let controlCommand = e.pen.controlCommand.filter(
        item => item.id == e.params
      )[0];
      commanddevice(controlCommand);
    }
  });
}
// const DebounceDeviceControl = customPromiseDebounce(deviceControl, 1000, true);
const commanddevice = (controlCommand: any) => {
  let item = controlCommand.command;
  const loading = ref(false)
  if (item.paramType == 1) {
    addDialog({
      title: item.commandName,
      width: "428px",
      draggable: true,
      fullscreenIcon: true,
      props: {
        options: item.value3,
        modelValue: null,
        isLoading: true
      },
      hideFooter: false,
      closeOnClickModal: false,
      footerButtons: [
        {
          label: "取消",
          text: false,
          bg: true,
          btnClick: ({ dialog: { options, index } }) => {
            const done = () =>
              closeDialog(options, index, { command: "cancel" });
            if (options?.beforeCancel && isFunction(options?.beforeCancel)) {
              options.beforeCancel(done, { options, index });
            } else {
              done();
            }
          }
        },
        {
          label: "确定",
          type: "primary",
          text: false,
          bg: true,
          loading: loading,
          btnClick: ({ dialog: { options, index } }) => {
            const done = () =>
              closeDialog(options, index, { command: "sure" });
            if (options?.beforeSure && isFunction(options?.beforeSure)) {
              options.beforeSure(done, { options, index });
            } else {
              done();
            }
          }
        }
      ],
      contentRenderer: () =>
        h('div', `确定要执行${item.commandName}命令吗?`),
      beforeSure: (done, { options }) => {
        loading.value = true
        deviceControl({
          projectId: configurationPage.projectId,
          deviceId: controlCommand.device.id,
          commandId: controlCommand.command.id,
          param: null
        }).then(res => {
          ElMessage({
            type: "success",
            message: res.msg
          });
          done()
        }).finally(() => {
          loading.value = false
        });
      }
    });
  } else if (item.paramType == 2) {
    const formRef = ref()
    const selectidvalue1 = ref(null)
    addDialog({
      title: item.commandName,
      width: "428px",
      draggable: true,
      fullscreenIcon: true,
      props: {
        options: item.value3,
        modelValue: null,
        isLoading: true
      },
      hideFooter: false,
      closeOnClickModal: false,
      footerButtons: [
        {
          label: "取消",
          text: false,
          bg: true,
          btnClick: ({ dialog: { options, index } }) => {
            const done = () =>
              closeDialog(options, index, { command: "cancel" });
            if (options?.beforeCancel && isFunction(options?.beforeCancel)) {
              options.beforeCancel(done, { options, index });
            } else {
              done();
            }
          }
        },
        {
          label: "确定",
          type: "primary",
          text: false,
          bg: true,
          loading: loading,
          btnClick: ({ dialog: { options, index } }) => {
            const done = () =>
              closeDialog(options, index, { command: "sure" });
            if (options?.beforeSure && isFunction(options?.beforeSure)) {
              options.beforeSure(done, { options, index });
            } else {
              done();
            }
          }
        }
      ],
      contentRenderer: () =>
        h(datainput, {
          ref: formRef,
          "onUpdate:modelValue": val => {
            selectidvalue1.value = val;
          }
        }),
      openAutoFocus({ options }) {
        options.props = {
          isLoading: true,
          formInline: {
            inputvalue: null
          },
          qujianzhi: item,
          activevalue: null
        };
        if (item.hasConfig == 1) {
          commandconfig({
            deviceId: controlCommand.device.id,
            commandId: item.id
          })
            .then(res => {
              options.props.formInline.inputvalue = res.result
              options.props.isLoading = false;
            })
            .catch(() => {
              options.props.isLoading = false;
              ElMessage({
                type: "error",
                message: "读取配置失败"
              });
            });
        } else {
          options.props.isLoading = false;
        }

      },
      beforeSure: (done, { options }) => {
        const formData = options.props.formInline;
        if (formData.inputvalue == null) {
          ElMessage({
            type: "warning",
            message: "请输入参数值"
          });
          return;
        }
        loading.value = true
        deviceControl({
          projectId: configurationPage.projectId,
          deviceId: controlCommand.device.id,
          commandId: controlCommand.command.id,
          param: formData.inputvalue
        }).then((res: any) => {
          if (res.code == 200) {
            done();
            ElMessage({
              type: "success",
              message: res.msg
            });
          }
        }).finally(() => {
          loading.value = false
        });
      }
    });
  } else {
    const formRef = ref();
    const selectidvalue = ref(null);
    addDialog({
      title: item.commandName,
      width: "428px",
      draggable: true,
      fullscreenIcon: true,
      props: {
        options: item.value3,
        modelValue: null,
        isLoading: true,
        activevalue: null
      },
      hideFooter: false,
      closeOnClickModal: false,
      footerButtons: [
        {
          label: "取消",
          text: false,
          bg: true,
          btnClick: ({ dialog: { options, index } }) => {
            const done = () =>
              closeDialog(options, index, { command: "cancel" });
            if (options?.beforeCancel && isFunction(options?.beforeCancel)) {
              options.beforeCancel(done, { options, index });
            } else {
              done();
            }
          }
        },
        {
          label: "确定",
          type: "primary",
          text: false,
          bg: true,
          loading: loading,
          btnClick: ({ dialog: { options, index } }) => {
            const done = () =>
              closeDialog(options, index, { command: "sure" });
            if (options?.beforeSure && isFunction(options?.beforeSure)) {
              options.beforeSure(done, { options, index });
            } else {
              done();
            }
          }
        }
      ],
      contentRenderer: () =>
        h(dataselect, {
          ref: formRef,
          "onUpdate:modelValue": val => {
            selectidvalue.value = val;
          }
        }),
      openAutoFocus({ options, index }) {
        options.props = {
          isLoading: true,
          modelValue: null,
          options: item.value3,
          activevalue: null
        };
        if (item.hasConfig == 1) {
          commandconfig({
            deviceId: controlCommand.device.id,
            commandId: item.id
          })
            .then(res => {
              options.props.activevalue = res.result;
              options.props.isLoading = false;
            })
            .catch(err => {
              options.props.isLoading = false;
              ElMessage({
                type: "error",
                message: "读取配置失败"
              });
            });
        } else {
          options.props.isLoading = false;
        }
      },
      beforeSure: (done, { options }) => {
        if (selectidvalue.value == null) {
          ElMessage({
            type: "warning",
            message: "请选择"
          });
          return;
        } else {
          loading.value = true;
          deviceControl({
            projectId: configurationPage.projectId,
            deviceId: controlCommand.device.id,
            commandId: controlCommand.command.id,
            param: selectidvalue.value
          }).then(res => {
            ElMessage({
              type: "success",
              message: res.msg
            });
            if (res.code == 200) {
              done();
            }
          }).finally(() => {
            loading.value = false;
          });
        }
      }
    });
  }
};
function handleCommand(controlCommand, inputValue) {
  let item = controlCommand.command;
  ElMessageBox.prompt(
    `请输入${item.value2[0]}-${item.value2[1]}内的参数`,
    item.commandName,
    {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      inputPlaceholder: `请输入${item.value2[0]}-${item.value2[1]}`,
      inputErrorMessage: `请输入${item.value2[0]}-${item.value2[1]}`,
      inputValue: inputValue,
      inputValidator: value => {
        item.value2 = item.value2.map(Number);
        if (value) {
          if (
            Math.min(...item.value2) <= parseFloat(value) &&
            parseFloat(value) <= Math.max(...item.value2)
          ) {
            return true;
          } else {
            return `请输入${item.value2[0]}-${item.value2[1]}之间的参数`;
          }
        } else {
          return `请输入参数`;
        }
      }
    }
  ).then(({ value }) => {
    deviceControl({
      projectId: configurationPage.projectId,
      deviceId: controlCommand.device.id,
      commandId: controlCommand.command.id,
      param: value
    }).then(res => {
      ElMessage({
        type: "success",
        message: res.msg
      });
    });
  });
}
function initEventListener() {
  window.addEventListener("resize", onResize, false);

  if (props.editable) {
    window.meta2d.on("scale", (number: number) => {
      store.setEditorScale(Math.round(number * 100));
    });
    window.meta2d.on("add", () => {
      console.log("触发add");
      window.meta2d.initBindDatas();
      window.meta2d.emit("pensTreeChange");
    });
    window.meta2d.on("update", () => {
      window.meta2d.emit("pensTreeChange");
      const activePens = window.meta2d.canvas.store.active;
      if (activePens.length) {
        const rect = window.meta2d.getPenRect(activePens[0]);
        activePens.length === 1 &&
          store.setCurrentPenRect({
            x: Math.round(rect.x * 10) / 10,
            y: Math.round(rect.y * 10) / 10,
            width: Math.round(rect.width * 10) / 10,
            height: Math.round(rect.height * 10) / 10
          });
      }
      console.log("触发update");
    });
    window.meta2d.on("delete", () => {
      console.log("触发delete");
      store.currentPenLength = 0;
      window.meta2d.emit("pensTreeChange");
    });
    window.meta2d.on("contextmenu", onOpenContextMenu);
    document.addEventListener("contextmenu", preventDefault, false);
  }
  window.meta2d.on("active", () => {
    console.log("触发active");
    const activePens = window.meta2d.canvas.store.active;
    console.log(activePens);
    store.setEditorActiveType(
      activePens.length === 0
        ? EditorActiveType.CanvasActive
        : activePens.length > 1
          ? EditorActiveType.CombineActive
          : EditorActiveType.PenActive
    );
    store.setCurrentPenLength(activePens.length);
    activePens.length === 1 && store.setCurrentPen(activePens[0]);
    activePens.length === 1 &&
      store.setCurrentPenRect(window.meta2d.getPenRect(activePens[0]));
    activePens.length > 1 && store.setCurrentPens(activePens);
    console.log(store.currentPenLength);
    console.log(store.currentPens);
    window.meta2d.emit("pensTreeChange");
  });
  window.meta2d.on("inactive", () => {
    store.setEditorActiveType(EditorActiveType.CanvasActive);
    window.meta2d.emit("pensTreeChange");
  });
  window.meta2d.on("click", onClick);
}
function onResize() {
  window.meta2d.resize();
}
function onOpenContextMenu(event: { e: MouseEvent }) {
  let { e } = event;
  positionX.value = e.clientX;
  positionY.value = e.clientY;

  const { active: activePens, histories, historyIndex } = window.meta2d.store;
  const len = activePens.length;
  const hisLen = histories.length;

  contextmenuList.value = [
    {
      type: "menu-item",
      icon: "el-icon-upload2",
      title: "置顶",
      value: "top",
      shortcut: "",
      disabled: len === 0,
      visible: true
    },
    {
      type: "menu-item",
      icon: "el-icon-download",
      title: "置底",
      value: "bottom",
      shortcut: "",
      disabled: len === 0,
      visible: true
    },
    {
      type: "menu-item",
      icon: "el-icon-top",
      title: "上一个图层",
      value: "up",
      shortcut: "",
      disabled: len === 0,
      visible: true
    },
    {
      type: "menu-item",
      icon: "el-icon-bottom",
      title: "下一个图层",
      value: "down",
      shortcut: "",
      disabled: len === 0,
      visible: true
    },
    { type: "split-line" },
    {
      type: "menu-item",
      icon: "el-icon-connection",
      title: "添加/删除锚点",
      value: "anchors",
      shortcut: "",
      disabled: len > 1,
      visible: true
    },
    {
      type: "menu-item",
      icon: "el-icon-connection",
      title: "组合",
      value: "combine",
      shortcut: "",
      disabled: len === 0,
      visible: len > 1
    },
    {
      type: "menu-item",
      icon: "el-icon-connection",
      title: "组合为状态",
      value: "combineStatus",
      shortcut: "",
      disabled: len === 0,
      visible: len > 1
    },
    {
      type: "menu-item",
      icon: "el-icon-copy-document",
      title: "取消组合",
      value: "uncombine",
      shortcut: "",
      disabled: len === 0,
      visible: len === 1 && activePens[0].name === "combine"
    },
    {
      type: "menu-item",
      icon: "el-icon-lock",
      title: "锁定",
      value: "lock",
      shortcut: "",
      disabled: len === 0,
      visible: len > 0 && !activePens[0].locked
    },
    {
      type: "menu-item",
      icon: "el-icon-unlock",
      title: "解锁",
      value: "unlock",
      shortcut: "",
      disabled: len === 0,
      visible: len > 0 && activePens[0].locked
    },
    { type: "split-line" },
    {
      type: "menu-item",
      icon: "el-icon-delete",
      title: "删除",
      value: "remove",
      shortcut: "Del",
      disabled: len === 0,
      visible: true
    },
    { type: "split-line" },
    {
      type: "menu-item",
      icon: "el-icon-delete",
      title: "撤销",
      value: "undo",
      shortcut: "Ctrl + Z",
      disabled: hisLen === 0 || historyIndex < 0,
      visible: true
    },
    {
      type: "menu-item",
      icon: "el-icon-delete",
      title: "恢复",
      value: "redo",
      shortcut: "Shift + Z",
      disabled: hisLen > 0 && historyIndex === hisLen - 1,
      visible: true
    },
    { type: "split-line" },
    {
      type: "menu-item",
      icon: "el-icon-document-copy",
      title: "复制",
      value: "copy",
      shortcut: "Ctrl + C",
      disabled: len === 0,
      visible: true
    },
    {
      type: "menu-item",
      icon: "el-icon-scissors",
      title: "剪切",
      value: "cut",
      shortcut: "Ctrl + X",
      disabled: len === 0,
      visible: true
    },
    {
      type: "menu-item",
      icon: "el-icon-tickets",
      title: "粘贴",
      value: "paste",
      shortcut: "Ctrl + V",
      disabled: false,
      visible: true
    }
  ];

  showContextmenu.value = true;
}

function onClick(pen: Pen, e: Point) {
  console.log("click", pen, e);

  const activePens = window.meta2d.canvas.store.active;
  store.setCurrentPenLength(activePens.length);
  // 根据自己的需求实现
  showContextmenu.value = false;
}
function onContextMenuClick(type: string) {
  showContextmenu.value = false;
  const activePens = window.meta2d.store.active;
  const pen = activePens[0];
  switch (type) {
    case "top":
      pen && window.meta2d.top(pen);
      break;
    case "bottom":
      pen && window.meta2d.bottom(pen);
      break;
    case "up":
      pen && window.meta2d.up(pen);
      break;
    case "down":
      pen && window.meta2d.down(pen);
      break;
    case "combine":
      window.meta2d.combine(activePens);
      break;
    case "combineStatus":
      window.meta2d.combine(activePens, 0);
      break;
    case "uncombine":
      pen && pen.name === "combine" && window.meta2d.uncombine(pen);
      break;
    case "lock":
      if (activePens.length > 0) {
        activePens.forEach((pen: { id: string }) => {
          window.meta2d.setValue(
            { id: pen.id, locked: LockState.DisableEdit },
            { render: false, history: true }
          );
        });
        window.meta2d.render();
      }
      break;
    case "unlock":
      if (activePens.length > 0) {
        activePens.forEach((pen: { id: string }) => {
          window.meta2d.setValue(
            { id: pen.id, locked: LockState.None },
            { render: false, history: true }
          );
        });
        window.meta2d.render();
      }
      break;
    case "remove":
      activePens.length > 0 && window.meta2d.delete(activePens);
      break;
    case "undo":
      window.meta2d.undo();
      break;
    case "redo":
      window.meta2d.redo();
      break;
    case "copy":
      window.meta2d.copy();
      break;
    case "cut":
      window.meta2d.cut();
      break;
    case "paste":
      window.meta2d.paste();
      break;
    case "anchors":
      window.meta2d.toggleAnchorMode();
      break;
    default:
      break;
  }
}
function preventDefault(e: { preventDefault: () => void }) {
  e.preventDefault();
}
onUnmounted(() => {
  window.removeEventListener("resize", onResize);
  window.removeEventListener("contextmenu", preventDefault);
  window.meta2d.destroy();
  clearTimer();
});
</script>

<style lang="scss" scoped>
.canvas-wrapper {
  width: 100%;
  height: 100%;
}

#editor-canvas {
  width: 100%;
  height: 100%;
}
</style>
